Passed
Push — master ( 26fe41...bccb07 )
by EMP
01:18
created

main.js ➔ deleteAddress   D

Complexity

Conditions 13

Size

Total Lines 38
Code Lines 24

Duplication

Lines 38
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 24
dl 38
loc 38
rs 4.2
c 0
b 0
f 0
cc 13

How to fix   Complexity   

Complexity

Complex classes like main.js ➔ deleteAddress often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		document.getElementById("txt_skey").style.background = "#404b41";
8
		document.getElementById("txt_skey").maxLength = "64";
9
	} else {
10
		console.log("Failed to load All-Ears");
11
	}
12
});
13
14
let tab="inbox";
15
let page=0;
16
17
// Helper functions
18
function getCountryName(countryCode) {
19
	const opts = document.getElementById("gatekeeper_country");
20
21
	for (let i = 0; i < opts.length; i++) {
22
		if (opts[i].value === countryCode) {
23
			return opts[i].textContent;
24
		}
25
	}
26
27
	return "Unknown countrycode: " + countryCode;
28
}
29
30
function getCountryFlag(countryCode) {
31
	const regionalIndicator1 = 127462 + countryCode.codePointAt(0) - 65;
32
	const regionalIndicator2 = 127462 + countryCode.codePointAt(1) - 65;
33
	return "&#" + regionalIndicator1 + ";&#" + regionalIndicator2 + ";";
34
}
35
36
function displayMsg(isInt, num) {
37
	document.getElementById("midright").scroll(0, 0);
38
39
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
40
41
	document.getElementById("btn_reply").disabled = false;
42
	document.getElementById("btn_reply").onclick = function() {
43
		document.getElementById("write_recv").value = isInt ? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
44
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
45
		document.getElementById("btn_write").click();
46
		document.getElementById("write_body").focus();
47
		for (const opt of document.getElementById("write_from").options) {
48
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
49
				opt.selected = true;
50
			}
51
		}
52
	};
53
54
	document.getElementById("msg").hidden = false;
55
	document.getElementById("msg").getElementsByTagName("h1")[0].textContent = isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num);
56
	document.getElementById("msg").getElementsByTagName("pre")[0].textContent = isInt ? ae.GetIntMsgBody(num) : ae.GetExtMsgBody(num);
57
58
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
59
	document.getElementById("readmsg_date").textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " ");
60
61
	if (!isInt) {
62
		const cc = ae.GetExtMsgCountry(num);
63
64
		document.getElementById("readmsg_greet").textContent = ae.GetExtMsgGreet(num);
65
		document.getElementById("readmsg_ip").textContent = ae.GetExtMsgIp(num);
66
		document.getElementById("readmsg_tls").textContent = ae.GetExtMsgTLS(num);
67
		document.getElementById("readmsg_country").innerHTML = getCountryFlag(cc) + " " + getCountryName(cc);
68
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
69
70
		let flagText = "";
71
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
72
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
73
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
74
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
75
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
76
		document.getElementById("readmsg_flags").innerHTML = flagText.trim();
77
	} else {
78
		document.getElementById("readmsg_from").textContent = ae.GetIntMsgFrom(num);
79
	}
80
}
81
82
// Interface
83
function addMsg(isInt, i) {
84
	const inbox = document.getElementById("tbl_inbox");
85
	const sent = document.getElementById("tbl_sent");
86
87
	const isSent = isInt? ae.GetIntMsgIsSent(i) : false;
88
	const table = isSent ? sent : inbox;
89
90
	const row = table.insertRow(-1);
91
	const cellTime = row.insertCell(-1);
92
	const cellSubj = row.insertCell(-1);
93
	const cellSnd1 = row.insertCell(-1);
94
	const cellSnd2 = row.insertCell(-1);
95
96
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
97
	cellTime.setAttribute("data-ts", ts);
98
	cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " ");
99
100
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
101
102
	if (isInt) {
103
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
104
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 24) ? "mono" : "";
105
	} else {
106
		const from1 = ae.GetExtMsgFrom(i);
107
		const from2 = from1.substring(from1.indexOf("@") + 1);
108
		const cc = ae.GetExtMsgCountry(i);
109
110
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
111
		cellSnd2.innerHTML = "<abbr title=\"" + getCountryName(cc) + "\">" + getCountryFlag(cc) + "</abbr>";
112
113
		const fromText = document.createElement("span");
114
		fromText.textContent = " " + from2;
115
		cellSnd2.appendChild(fromText);
116
	}
117
118
//	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">";
119
120
	row.onclick = function() {
121
		displayMsg(isInt, i);
122
	};
123
/*
124
	cellDel.children[0].onchange = function() {
125
		if (!divDel.children[0].checked) {
126
			const checkboxes = elmt.getElementsByTagName("input");
127
			let checked = false;
128
129
			for (let j = 0; j < checkboxes.length; j++) {
130
				if (checkboxes[j].checked) {
131
					checked = true;
132
					break;
133
				}
134
			}
135
136
			if (!checked) {
137
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
138
				return;
139
			}
140
		}
141
142
		document.getElementById(isSent? "btn_sentdel" : "btn_msgdel").hidden = false;
143
	};
144
*/
145
}
146
147
function addMessages() {
148
	const maxExt = ae.GetExtMsgCount();
149
	const maxInt = ae.GetIntMsgCount();
150
151
	let numExt = 0;
152
	let numInt = 0;
153
154
	for (let i = 0; i < (page * 20) + 20; i++) {
155
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : 0;
156
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : 0;
157
		if (tsInt === 0 && tsExt === 0) break;
158
159
		if (tsInt !== 0 && (tsExt === 0 || tsInt > tsExt)) {
160
			if (i < (page * 20)) {
161
				numInt++;
162
				continue;
163
			}
164
165
			addMsg(true, numInt);
166
			numInt++;
167
		} else if (tsExt !== 0) {
168
			if (i < (page * 20)) {
169
				numExt++;
170
				continue;
171
			}
172
173
			addMsg(false, numExt);
174
			numExt++;
175
		}
176
	}
177
}
178
179
function clearMessages() {
180
	document.getElementById("tbl_inbox").innerHTML = "";
181
//	document.getElementById("tbl_sentm").innerHTML = "";
182
//	document.getElementById("tbl_notes").innerHTML = "";
183
//	document.getElementById("tbl_files").innerHTML = "";
184
}
185
186
function updateAddressCounts() {
187
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetAddressLimitNormal(ae.GetUserLevel())).padStart(ae.GetAddressLimitNormal(ae.GetUserLevel()) > 9 ? 5 : 1);
188
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetAddressLimitShield(ae.GetUserLevel())).padStart(ae.GetAddressLimitShield(ae.GetUserLevel()) > 9 ? 5 : 1);
189
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
190
}
191
192
function reloadInterface() {
193
	document.getElementById("div_begin").hidden = true;
194
	document.getElementById("div_main").style.display = "grid";
195
196
	// Contacts
197
	for (let i = 0; i < ae.GetContactCount(); i++) {
198
		addContact(
199
			ae.GetContactMail(i),
200
			ae.GetContactName(i),
201
			ae.GetContactNote(i)
202
		);
203
	}
204
205
	// Addresses
206
	for (let i = 0; i < ae.GetAddressCount(); i++) {
207
		addAddress(i);
208
	}
209
210
	document.getElementById("table_addrs").getElementsByTagName("caption")[0].textContent = "Level " + ae.GetUserLevel() + " User";
211
	updateAddressCounts();
212
}
213
214 View Code Duplication
function deleteAddress(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
215
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
216
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
217
218
	let addressToDelete = -1;
219
220
	for (let i = 0; i < ae.GetAddressCount(); i++) {
221
		if (addr === ae.GetAddress(i)) {
222
			addressToDelete = i;
223
			break;
224
		}
225
	}
226
227
	if (addressToDelete === -1) return;
228
229
	ae.Address_Delete(addressToDelete, function(success) {
230
		if (success) {
231
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
232
			document.getElementById("write_from").remove(addressToDelete);
233
			updateAddressCounts();
234
235
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
236
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
237
238
			ae.Private_Update(function(success2) {
239
				if (!success2) console.log("Failed to update the Private field");
240
241
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
242
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
243
			});
244
		} else {
245
			console.log("Failed to delete address");
246
247
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
248
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
249
		}
250
	});
251
}
252
253 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
254
	let newAddr = "";
255
256
	for (let i = 0; i < 24; i++) {
257
		switch (addr.charAt(i)) {
258
			case '1':
259
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
260
				break;
261
			case '0':
262
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
263
				break;
264
			case 'w':
265
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
266
				break;
267
			default:
268
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
269
		}
270
	}
271
272
	return newAddr;
273
}
274
275
function addAddress(num) {
276
	const addrTable = document.getElementById("tbl_addrs");
277
	const row = addrTable.insertRow(-1);
278
	const cellAddr = row.insertCell(-1);
279
	const cellChk1 = row.insertCell(-1);
280
	const cellChk2 = row.insertCell(-1);
281
	const cellChk3 = row.insertCell(-1);
282
	const cellBtnD = row.insertCell(-1);
283
284
	cellAddr.textContent = ae.GetAddress(num);
285
	cellAddr.onclick = function() {
286
		if (cellAddr.textContent.length === 24)
287
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomain());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
288
		else
289
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomain());
290
	};
291
292
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
293
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
294
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
295
296
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
297
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
298
299
	const opt = document.createElement("option");
300
	opt.value = cellAddr.textContent;
301
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomain();
302
	document.getElementById("write_from").appendChild(opt);
303
}
304
305
document.getElementById("btn_updt").onclick = function() {
306
	const btn = this;
307
	btn.disabled = true;
308
	btn.blur();
309
310
	if (tab === "inbox") {
311
		ae.Message_Browse(0, function(successBrowse) {
312
			if (successBrowse) {
313
				clearMessages();
314
				addMessages();
315
				btn.disabled = false;
316
			} else {
317
				console.log("Failed to refresh");
318
				btn.disabled = false;
319
			}
320
		});
321
	}
322
};
323
324
function addContact(mail, name, note) {
325
	const tbl = document.getElementById("tbl_ctact");
326
	const row = tbl.insertRow(-1);
327
	const cellMail = row.insertCell(-1);
328
	const cellName = row.insertCell(-1);
329
	const cellNote = row.insertCell(-1);
330
	const cellBtnD = row.insertCell(-1);
331
332
	cellMail.textContent = mail;
333
	cellName.textContent = name;
334
	cellNote.textContent = note;
335
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
336
337
	cellMail.contentEditable = true;
338
	cellName.contentEditable = true;
339
	cellNote.contentEditable = true;
340
341
	cellBtnD.onclick = function() {row.remove();};
342
}
343
344
document.getElementById("btn_newcontact").onclick = function() {
345
	addContact("", "", "");
346
}
347
348
// Tabs
349
function setupButtons() {
350
	switch(tab) {
351
		case "inbox":
352
		case "snbox":
353
			document.getElementById("btn_dele").disabled = false;
354
			document.getElementById("btn_left").disabled = false; // depends
355
			document.getElementById("btn_cent").disabled = true;
356
			document.getElementById("btn_rght").disabled = false;
357
			document.getElementById("btn_updt").disabled = false;
358
			break;
359
		case "write":
360
			document.getElementById("btn_dele").disabled = false; // depends
361
			document.getElementById("btn_left").disabled = false; // depends
362
			document.getElementById("btn_cent").disabled = true;
363
			document.getElementById("btn_rght").disabled = false;
364
			document.getElementById("btn_updt").disabled = true;
365
			break;
366
		case "notes":
367
			document.getElementById("btn_dele").disabled = true;
368
			document.getElementById("btn_left").disabled = false; // depends
369
			document.getElementById("btn_cent").disabled = true;
370
			document.getElementById("btn_rght").disabled = false; // depends
371
			document.getElementById("btn_updt").disabled = true; // depends
372
			break;
373
		case "prefs":
374
			document.getElementById("btn_dele").disabled = true;
375
			document.getElementById("btn_left").disabled = false; // depends
376
			document.getElementById("btn_cent").disabled = true;
377
			document.getElementById("btn_rght").disabled = false; // depends
378
			document.getElementById("btn_updt").disabled = true; // depends
379
			break;
380
	}
381
}
382
383
for (const btn1 of document.getElementById("main1").getElementsByClassName("top")[0].getElementsByTagName("button")) {
384
	btn1.onclick = function() {
385
		for (const btn2 of document.getElementById("main1").getElementsByClassName("top")[0].getElementsByTagName("button")) {
386
			const isMatch = (btn1 === btn2);
387
			btn2.disabled = isMatch;
388
			document.getElementById("div_" + btn2.id.slice(4)).hidden = !isMatch;
389
390
			if (isMatch) {
391
				tab = btn2.id.slice(4);
392
				setupButtons();
393
			}
394
		};
395
	};
396
};
397
398
function addressCreate(addr) {
399
	const btnN = document.getElementById("btn_address_create_normal");
400
	const btnS = document.getElementById("btn_address_create_shield");
401
	btnN.disabled = true;
402
	btnS.disabled = true;
403
404
	ae.Address_Create(addr, function(success1) {
405
		if (success1) {
406
			ae.Private_Update(function(success2) {
407
				addAddress(ae.GetAddressCount() - 1);
408
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
409
				updateAddressCounts();
410
411
				if (!success2) console.log("Failed to update the Private field");
412
413
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
414
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
415
			});
416
		} else {
417
			console.log("Failed to add address");
418
419
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
420
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
421
		}
422
	});
423
}
424
425
document.getElementById("btn_address_create_normal").onclick = function() {
426
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
427
428
	const txtNewAddr = document.getElementById("txt_address_create_normal");
429
	if (!txtNewAddr.reportValidity()) return;
430
431
	addressCreate(txtNewAddr.value);
432
}
433
434
document.getElementById("btn_address_create_shield").onclick = function() {
435
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
436
437
	addressCreate("SHIELD");
438
};
439
440
document.getElementById("txt_skey").onkeyup = function(event) {
441
	if (event.key === "Enter") {
442
		event.preventDefault();
443
		document.getElementById("btn_enter").click();
444
	}
445
};
446
447
document.getElementById("btn_enter").onclick = function() {
448
	const txtSkey = document.getElementById("txt_skey");
449
	if (!txtSkey.reportValidity()) return;
450
451
	const btn = this;
452
	btn.disabled = true;
453
	document.getElementById("txt_skey").style.background = "#111";
454
455
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
456
		if (successSetKeys) {
457
			ae.Account_Browse(0, function(successBrowse) {
458
				if (successBrowse) {
459
					txtSkey.value = "";
460
					reloadInterface();
461
					document.getElementById("btn_updt").click();
462
				} else {
463
					console.log("Failed to enter");
464
					btn.disabled = false;
465
					document.getElementById("txt_skey").style.background = "#404b41";
466
					txtSkey.focus();
467
				}
468
			});
469
		} else {
470
			console.log("Invalid format for key");
471
			btn.disabled = false;
472
			document.getElementById("txt_skey").style.background = "#404b41";
473
			txtSkey.focus();
474
		}
475
	});
476
};
477
478
});
479